我們終於要正式開始時做一個後台(dashboard)畫面啦,今天我們會先使用Angular Material的SideNav元件,把邊欄的空間先切出來,這個空間通常是用來放置主選單的空間,我們就來看看該如何開始吧!
在Material Design的架構指南中,一個應用程式不管是行動裝置、平板還是桌機,在畫面基本上都可以分為3個區塊,toolbar、sidenav和content
圖片來源:https://material.io/guidelines/layout/structure.html#structure-ui-regions
在使用SideNav前,我們一樣要將MatSidenavModule
加入,這個步驟之前已經做過很多次了,就只說明不介紹步驟;另外由於我們之後會再持續設計部落格頁面、問卷頁面等等,因此已將程式切割到不同的Module中並設定好routing,由於這是屬於Angular基本知識,這裡也不再多做說明,程式碼都在GitHub上,可以直接參考。
加入MatSidenavModule
後,我們就可以直接開始使用,基本上SideNav分為3個區塊
<mat-sidenav-container>
:代表整個包含邊欄導覽的容器<mat-sidenav>
:實際上邊欄導覽的內容<mat-sidenav-content>
:導覽以外的實際內容因此我們的畫面程式碼可以簡單寫成如下:
<mat-sidenav-container>
<mat-sidenav #sideNav>
我是左邊選單
</mat-sidenav>
<mat-sidenav-content>
<button mat-button (click)="sideNav.toggle()">切換左邊選單狀態</button>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
一個包含導覽功能的選單就已經出現啦!不過這時候我們的畫面上還不會將選單顯示出來,這是因為Angular Material預設的<mat-sidenav>
是隱藏的,不過我們可以透過程式把選單叫出來,所以畫面上我們先建立了一個按鈕,透過這個按鈕呼叫sideNav的toggle()
方法,來切換左邊導覽列的顯示狀態。
結果如下:
我們可以透過open()
、close()
和toggle()
來控制SideNav的顯示狀態,這些方法都會回傳一個Promise<MatDrawerToggleResult>
來告訴你SideNav的顯示狀態。
toggleSideNav(sideNav: MatSidenav) {
sideNav.toggle().then((result: MatDrawerToggleResult) => {
console.log(result);
console.log(`選單狀態:${result.type}`);
});
}
結果如下:
除此之外SideNav還有opened
和closed
,兩個output,當SideNav被打開或關時,就會觸發。
<mat-sidenav #sideNav (opened)="opened()" (closed)="closed()">
<mat-side-nav>
有一個mode屬性,可以用來決定SideNav的呈現方式,目前有3個值可以設定
over :預設值,SideNav會浮動在畫面之上,背後會出現一個灰底的backdrop,點擊SideNav以外的地方(或按下ESC)會隱藏起來。
push :跟over類似,但顯示的時候會把畫面往另外一個方向推,同時也會有一個灰底的backdrop,在螢幕較大的裝置時可以同時瀏覽SideNav和選單,但在行動裝置等小螢幕上則比較沒有感覺。
side :效果類似push,但不會出現灰底的backdrop,因此可以同時操作主要的content畫面以及SideNav的內容。
透過opened
屬性,我們可以不需要使用元件的open()
或toggle()
方法來打開,只需要設定這個屬性即可變更顯示狀態,true代表顯示,false代表隱藏。因此當我們需要一個固定在旁邊的導覽選單時,可以同時將mode設為side,並將opened設為true,即可讓導覽選單常駐在旁邊,只要不在程式中切換這些狀態,就不會被隱藏。
<mat-sidenav opened="true" mode="side"></mat-sidenav>
SideNav支援顯示在畫面的起始(start
,預設值,通常是左邊)或結束(end
,通常是右邊),我們可以透過設定position
決定SideNav要放在哪邊,同時我們也能左右各提供一個導覽選單。
<mat-sidenav opened="true" mode="side">
<div>我是左邊選單</div>
</mat-sidenav>
<mat-sidenav opened="true" mode="side" position="end">
<div>我是右邊選單</div>
</mat-sidenav>
結果如下:
不過需要注意的是,左右都只能有1個SideNav,因此以下寫法都是不正確的
<mat-sidenav opened="true" mode="side">
<div>我是左邊選單</div>
</mat-sidenav>
<mat-sidenav opened="true" mode="side" position="start">
<div>我是左邊選單2號</div>
</mat-sidenav>
<mat-sidenav opened="true" mode="side" position="end">
<div>我是右邊選單</div>
</mat-sidenav>
<mat-sidenav opened="true" mode="side" position="end">
<div>我是右邊選單2號</div>
</mat-sidenav>
當這樣的狀況出現時,會看到以下的錯誤訊息
在mode設為over
或push
時,預設會出現一個backdrop,當點選backdrop或按下esc
時則會自動隱藏SideNav,如果希望不要自動隱藏,則可以設定disabledClose
,有了這個屬性就必須另外在可點選的範圍內加上程式設定隱藏SideNav。
<mat-sidenav #sideNav mode="over" disableClose>
<div>我是左邊選單</div>
<div>
<button mat-raised-button color="warn" (click)="toggleSideNav(sideNav)">切換選單狀態</button>
</div>
</mat-sidenav>
當我們有一個toolbar在上層時,預設SideNav現時不會擋住toolbar
<mat-toolbar>我是Toolbar</mat-toolbar>
<mat-sidenav-container>
<mat-sidenav #sideNav mode="over">
<div>我是左邊選單</div>
<div>
<button mat-raised-button color="warn" (click)="toggleSideNav(sideNav)">切換選單狀態</button>
</div>
</mat-sidenav>
...
</mat-sidenav-container>
如下圖:
這時候我們可以設定fixedInViewport="true"
,讓SideNav能夠顯示在Toolbar之上。另外也能設定fixedTopGap
和fixedBottomGap
,保留一定程度的上下空間。
<mat-sidenav #sideNav mode="over" fixedInViewport="true" fixedTopGap="20" fixedBottomGap="20"></mat-sidenav>
結果如下:
關於Toolbar的使用方式會在明天詳細說明。
除了SideNav之外,Angular Material還提供了一個類似的component-<mat-drawer>
。比起SideNav是設計給整個畫面使用,Drawer則是提供給放在content裡面小範圍區塊使用。除了不支援fixedInViewport
(畢竟沒有需要遮擋的toolbar了)以外,這個drawer component使用上基本和sidenav完全相同,
<mat-drawer-container style="height:100px;border: 1px solid black">
<mat-drawer mode="side" opened="true">Drawer Side</mat-drawer>
<mat-drawer-content>Content</mat-drawer-content>
</mat-drawer-container>
結果如下:
今天我們介紹了SideNav相關的元件,這是Material Design設計中對於一個基本的APP很重要的環節,因次SideNav也提供來了很多微調顯示效果,讓我們在設計時更能夠應付不同的情境。
明天我們將介紹畫面結構的另一個重要component-Toolbar
本日的程式碼GitHub:https://github.com/wellwind/it-ironman-demo-angular-material/tree/day-05-sidenav
分支:day-05-sidenav
很精采的文章。如果在Sidenav 加router-link, 按下時,component 是不是在sidebar-nav-content 內的router-outlet 出現?
謝謝您的肯定^^,關於您的問題,答案是肯定的,這跟Angular原始的routing機制沒有不同
謝
HI~謝謝您的分享!!
請問 sidenav 是否可以做成有 accordion 式的 material tag 呢?
我想做一個類似如下的sidenav
AAA
BBB
|_ BBB1
|_ BBB2
CCC
|_CCC1
|_CCC2
謝謝~~
您好,請問您的意思是sidenav「裡面」要放置accordion的選單嗎?
基本上sidenav裡面可以放置任何東西,如果是tree的結構選單的話,目前Angular Material還沒有提供,但可以參考使用Expansion Panel
https://ithelp.ithome.com.tw/articles/10196478
或是使用其他套件,或自行設計
謝謝
我是要在sidenav中放入accordion選單!!
目前改成使用您說的 expansion panel
感謝~
我的灰底backdrop沒有如預設的狀況下出現呢orz,不知什麼原因,所以也無法點擊backdrop來隱藏,over, push都沒有如期出現
狀況描述看起來是沒有正確的載入CSS,請參考 安裝篇 的步驟
感謝我再一個個試試看是哪個沒裝上去
大神好@@
< mat-toolbar >那邊似乎要加入MatToolbarModule才可以使用
這篇文章中似乎沒有提到(不過下一篇有XD)
disableClose
在 mode 設為 over 或 push 時.......如果希望不要自動隱藏,則可以設定disabledClose
。
disabledClose 多了個 d